﻿#region MyJScript - LGPL Copyright (c) 2008 Lionel Laské
//
// This file is part of MyJScript.
//
// MyJScript is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// MyJScript is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with MyJScript; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//================================================================================
#endregion

using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using MyJScript.Compiler;
using MyJScript.DLR;


namespace MyJScript.Test
{
    /// <summary>
    /// Unit tests for Parser.
    /// </summary>
    [TestClass]
    public class ParserTest
    {
        /// <summary>
        /// Set up DLR domain manager
        /// </summary>
        [TestInitialize]
        public void Initialize()
        {
            Utils.Initialize();
        }

        /// <summary>
        /// Delete temp files
        /// </summary>
        [TestCleanup]
        public void Cleanup()
        {
            Utils.Cleanup();
        }

        /// <summary>
        /// Parse source code and print error.
        /// </summary>
        /// <param name="source">source file</param>
        /// <returns>false if error</returns>
        private bool Parse(string source)
        {
            Parser p = new Parser(Utils.Source(source));
            bool res = true;
            try
            {
                p.Parse();
            }
            catch (SyntaxErrorException e)
            {
                Console.Error.WriteLine(e.ToString());
                res = false;
            }
            return res;
        }

        /// <summary>
        /// Test empty source file.
        /// </summary>
        [TestMethod]
        public void Empty()
        {
            Assert.IsTrue(Parse(null));
            Assert.IsTrue(Parse(""));
            Assert.IsTrue(Parse("   \r\n    \t\r\n"));
        }

        /// <summary>
        /// Test single statement.
        /// </summary>
        [TestMethod]
        public void SingleStatement()
        {
            Assert.IsTrue(Parse("var a;"));
            Assert.IsTrue(Parse("var _r='Hello!';"));
            Assert.IsTrue(Parse("while(i==0) i=i+1;"));
            Assert.IsTrue(Parse("write(12);"));
        }
        
        /// <summary>
        /// Test multiple statements.
        /// </summary>
        [TestMethod]
        public void MultipleStatement()
        {
            Assert.IsTrue(Parse(@"
                var i = 0;
                while (i<3)
                    i = i + 1;
            "));

            Assert.IsTrue(Parse(@"
                function hello() {
                    write(""Hello world!"");
                }

                hello();
            "));
        }

        
        /// <summary>
        /// Test when parsing error.
        /// </summary>
        [TestMethod]
        public void Error()
        {
            Parser p1 = new Parser(Utils.Source("#"));
            try
            {
                p1.Parse();
                Assert.Fail();
            }
            catch (SyntaxErrorException e)
            {
                Assert.AreEqual(100, e.ErrorCode);
                Assert.AreEqual(1, e.Column);
                Assert.AreEqual(1, e.Line);
            }
            
            Parser p2 = new Parser(Utils.Source("var a"));
            try
            {
                p2.Parse();
                Assert.Fail();
            }
            catch (SyntaxErrorException e)
            {
                Assert.AreEqual(200, e.ErrorCode);
                Assert.AreEqual(1, e.Line);
                Assert.AreEqual(6, e.Column);
            }

            Parser p3 = new Parser(Utils.Source("var b;\r\nb = var;"));
            try
            {
                p3.Parse();
            }
            catch (SyntaxErrorException e)
            {
                Assert.AreEqual(300, e.ErrorCode);
                Assert.AreEqual(2, e.Line);
                Assert.AreEqual(8, e.Column);
            }
        }
    }
}
